package com.hank.jdbc;

import com.hank.conf.ConfigurationManager;
import com.hank.constant.Constants;

import java.sql.*;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;

public class JDBCHelper {
    private static JDBCHelper instance = new JDBCHelper();
    //使用阻塞队列
    private LinkedBlockingDeque<Connection> queue = new LinkedBlockingDeque<>();
    static{
        try {
            //NEW DRIVER
            Class.forName(ConfigurationManager.getProperty(Constants.JDBC_DRIVER));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private JDBCHelper() {
        int dataSourceSize = ConfigurationManager.getInteger(Constants.JDBC_ACTIVE);
        String url = ConfigurationManager.getProperty(Constants.JDBC_URL);
        String username = ConfigurationManager.getProperty(Constants.JDBC_USERNAME);
        String password = ConfigurationManager.getProperty(Constants.JDBC_PASSWORD);
        //放进队列
        for(int i=0;i<dataSourceSize;i++){
            try {
                Connection connection = DriverManager.getConnection(url,username,password);
                queue.put(connection);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static JDBCHelper getInstance(){
        return instance;
    }

    /**
     * 获取数据库连接
     * 使用阻塞队列
     * @return
     */
    public Connection getConnection(){
        try {
            return queue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 更新数据
     * @param sql
     * @param params
     * @return
     */
    public int excuteUpdate(String sql,Object[] params){
        int re=0;
        Connection conn = null;
        PreparedStatement statement = null;

        try {
            conn = getConnection();
            statement = conn.prepareStatement(sql);
            for(int i=0;i<params.length;i++){
                statement.setObject(i+1,params[i]);
            }
            re = statement.executeUpdate();
            return re;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(conn != null){
                try {
                    queue.put(conn);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return re;
    }

    //定义QueryCallBack接口
    public static interface QueryCallBack
    {
        void process(ResultSet rs);
    }

    /**
     * 查询数据得处理
     * 使用接口得回调，根据用户得自定义接口来查询处理
     * @param sql
     * @param params
     * @param queryCallBack
     */
    public void excuteQuery(String sql,Object[] params,QueryCallBack queryCallBack){
        Connection conn = null;
        PreparedStatement statement =  null;

        try {
            conn = getConnection();
            statement = conn.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                statement.setObject(i+1,params[i]);
            }
            ResultSet rs=statement.executeQuery();
            queryCallBack.process(rs);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(conn != null){
                try {
                    queue.put(conn);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public int[] excuteBatch(String sql, List<Object[]> params)
    {
        Connection conn = null;
        PreparedStatement statement =  null;
        int[] res = null;

        try {
            conn = getConnection();
            statement = conn.prepareStatement(sql);
            conn.setAutoCommit(false);
            for(Object[] param : params){
                for(int i=0;i<param.length;i++){
                    statement.setObject(i+1,param[i]);
                }
                statement.addBatch();
            }
            //3.批量执行
            res = statement.executeBatch();
            //4.最后一步提交
            conn.commit();
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(conn != null){
                try {
                    queue.put(conn);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return res;
    }
}
